package com.stox.core.manager;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.stox.core.dao.ScripDao;
import com.stox.core.event.ApplicationEventPublisher;
import com.stox.core.event.ScripAddedEvent;
import com.stox.core.model.Scrip;
import com.stox.core.model.exception.StoxException;
import com.stox.core.ui.swing.util.ThrowableReporter;
import com.stox.design.AfterUiInitializable;
import com.stox.ioc.Container;

public class ScripManager implements AfterUiInitializable<Void, Void>{

	private ScripDao scripDao;
	private Map<String, Scrip> allScripMap;
	private Map<String, List<Scrip>> exchangeCodeScripMap = new HashMap<String, List<Scrip>>(2);
	
	public ScripManager() {
		this.allScripMap = new HashMap<String, Scrip>();
		this.scripDao = Container.get(ScripDao.class);
	}
	
	@Override
	public int getOrder() {
		return 1;
	}
	
	@Override
	public boolean isInitialized() {
		return allScripMap != null && !allScripMap.isEmpty();
	}
	
	@Override
	public Void invoke(Void payload) {
		try {
			List<Scrip> scrips = scripDao.get();
			for(Scrip scrip : scrips){
				allScripMap.put(scrip.getCode(), scrip);
				ApplicationEventPublisher.publish(new ScripAddedEvent(scrip));
			}
		} catch (SQLException e) {
			throw new StoxException(e);
		}
		return null;
	}
	
	public void updateMaxDate(String scripCode, Date maxDate){
		try{
			scripDao.updateMaxDate(scripCode, maxDate);
		}catch(SQLException e){
			throw new StoxException(e);
		}
	}
	
	public boolean exists(String scripCode){
		return allScripMap.containsKey(scripCode.trim());
	}
	
	public Collection<Scrip> findAll(){
		return allScripMap.values();
	}
	
	public Scrip findByCode(String code){
		return allScripMap.get(code);
	}
	
	public List<Scrip> get(Date date){
		try {
				return scripDao.get(date);
		} catch (SQLException e) {
			ThrowableReporter.report(e);
		}
		return Collections.emptyList();
	}

	
	public List<Scrip> findByIndexCode(String indexCode){
		try {
			List<Scrip> scrips = new ArrayList<Scrip>();
			List<String> scripCodes = scripDao.getScripCodesForIndexCode(indexCode);
			for(String scripCode : scripCodes){
				scrips.add(allScripMap.get(scripCode));
			}
			return scrips;
		} catch (SQLException e) {
			throw new StoxException(e);
		}
	}
	
	public List<Scrip> findBySectorCode(String sectorCode){
		try {
			List<Scrip> scrips = new ArrayList<Scrip>();
			List<String> scripCodes = scripDao.getScripCodesForSectorCode(sectorCode);
			for(String scripCode : scripCodes){
				scrips.add(allScripMap.get(scripCode));
			}
			return scrips;
		} catch (SQLException e) {
			throw new StoxException(e);
		}
	}
	
	public List<Scrip> findByExchangeCode(String exchangeCode){
		
		List<Scrip> scrips = exchangeCodeScripMap.get(exchangeCode);
		if(scrips == null){
			scrips = new ArrayList<Scrip>();
			for(Scrip scrip : allScripMap.values()){
				if(scrip.getExchangeCode().equalsIgnoreCase(exchangeCode)){
					scrips.add(scrip);
				}
			}
			Collections.sort(scrips);
			exchangeCodeScripMap.put(exchangeCode, scrips);
		}
		return scrips;
	}
	
	/*
	 * Do not raise scrip added event here
	 */
	public void persistAll(List<Scrip> scrips){
		try{
			scripDao.persistAll(scrips);
		}catch (SQLException e) {
			throw new StoxException(e);
		}
	}
	
	public boolean persist(Scrip scrip){
		if(exists(scrip.getCode())){
			return false;
		}
		
		try {
			scrip.format();
			scripDao.persist(scrip);
			allScripMap.put(scrip.getCode(), scrip);
			ApplicationEventPublisher.publish(new ScripAddedEvent(scrip));
		} catch (SQLException e) {
			throw new StoxException(e);
		}
		return true;
	}

	
}
